package com.weijianhuawen.wjblog.web.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.weijianhuawen.wjblog.common.domain.dos.ArticleDo;
import com.weijianhuawen.wjblog.common.domain.dos.WikiCatalogDo;
import com.weijianhuawen.wjblog.common.domain.dos.WikiDo;
import com.weijianhuawen.wjblog.common.domain.mapper.ArticleMapper;
import com.weijianhuawen.wjblog.common.domain.mapper.WikiCatalogMapper;
import com.weijianhuawen.wjblog.common.domain.mapper.WikiMapper;
import com.weijianhuawen.wjblog.common.enums.ResponseCodeEnum;
import com.weijianhuawen.wjblog.common.enums.WikiCatalogLevelEnum;
import com.weijianhuawen.wjblog.common.exception.BizException;
import com.weijianhuawen.wjblog.common.utils.PageResponse;
import com.weijianhuawen.wjblog.common.utils.Response;
import com.weijianhuawen.wjblog.web.convert.WikiConvert;
import com.weijianhuawen.wjblog.web.mode.vo.article.FindPreNextArticleRspVo;
import com.weijianhuawen.wjblog.web.mode.vo.wiki.*;
import com.weijianhuawen.wjblog.web.service.WikiService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @version: java version 8
 * @Author: weijianhuawen
 * @description:
 * @date: 2024-12-05 22:21
 */
@Service
@Slf4j
public class WikiServiceImpl implements WikiService {
    @Resource
    private WikiMapper wikiMapper;
    @Resource
    private WikiCatalogMapper wikiCatalogMapper;
    @Resource
    private ArticleMapper articleMapper;
    @Override
    public PageResponse findWikiPageList(FindWikiPageListReqVo vo) {
        // 获取请求分页参数
        Long current = vo.getCurrent();
        Long size = vo.getSize();

        // 获取分页数据页面
        Page<WikiDo> wikiPage = wikiMapper.selectPageList(current, size, null, null, null, true);
        // 获取数据记录
        List<WikiDo> wikiDos = wikiPage.getRecords();
        // 将do转换为vo
        List<FindWikiPageListRspVo> vos = Lists.newArrayList();
        if (!CollectionUtils.isEmpty(wikiDos)) {
            vos = wikiDos.stream()
                    .map(wikiDo -> WikiConvert.INSTANCE.wikiDo2FindWikiPageListRspVo(wikiDo))
                    .collect(Collectors.toList());

            // 设置每一个知识库的第一篇文章id，方便访问
            vos.forEach(findWikiPageListRspVo -> {
                Long wikiId = findWikiPageListRspVo.getId();
                WikiCatalogDo wikiCatalogDo = wikiCatalogMapper.selectFirstArticleId(wikiId);
                findWikiPageListRspVo.setFirstArticleId(Objects.nonNull(wikiCatalogDo) ? wikiCatalogDo.getArticleId() : null);
            });
        }
        return PageResponse.success(wikiPage, vos);
    }

    @Override
    public Response findWikiCatalogList(FindWikiCatalogListReqVo vo) {
        // 获取知识库id
        Long wikiId = vo.getId();
        // 获取该知识库下所绑定的目录
        List<WikiCatalogDo> wikiCatalogDos = wikiCatalogMapper.selectListByWikiId(wikiId);
        // 格式化目录
        List<FindWikiCatalogListRspVo> vos = catalogCollation(null, wikiCatalogDos, 1);
        return Response.success(vos);
    }

    @Override
    public Response findArticlePreNext(FindWikiArticlePreNextReqVo vo) {
        // 获取知识库id
        Long wikiId = vo.getWikiId();
        // 获取文章id
        Long articleId = vo.getArticleId();

        // 查询关联记录
        WikiCatalogDo wikiCatalogDo = wikiCatalogMapper.selectCatalogByWikiIdAndArticleId(wikiId, articleId);
        FindWikiArticlePreNextRspVo preNextRspVo = new FindWikiArticlePreNextRspVo();
        if (Objects.nonNull(wikiCatalogDo)) {
            // 存在目录，验证是否绑定文章
            ArticleDo articleDo = articleMapper.selectByArticleId(wikiCatalogDo.getArticleId());
            if (Objects.isNull(articleDo)) {
                // 绑定文章id不合法
                throw new BizException(ResponseCodeEnum.CATALOG_BIND_ILLEGAL_ARTICLE);
            }
            // 获取父目录id
            Long parentId = wikiCatalogDo.getParentId();
            // 获取sort
            Integer sort = wikiCatalogDo.getSort();
            // 查询上一篇
            WikiCatalogDo preCatalog = wikiCatalogMapper.selectPreCatalog(wikiId, parentId, sort);
            // 查询下一篇
            WikiCatalogDo nextCatalog = wikiCatalogMapper.selectNextCatalog(wikiId, parentId, sort);
            if (Objects.nonNull(preCatalog)) {
                FindPreNextArticleRspVo pre = FindPreNextArticleRspVo.builder()
                        .articleId(preCatalog.getArticleId())
                        .title(preCatalog.getTitle())
                        .build();

                preNextRspVo.setPreArticle(pre);
            }
            if (Objects.nonNull(nextCatalog)) {
                FindPreNextArticleRspVo next = FindPreNextArticleRspVo.builder()
                        .articleId(nextCatalog.getArticleId())
                        .title(nextCatalog.getTitle())
                        .build();

                preNextRspVo.setNextArticle(next);
            }
        }

        return Response.success(preNextRspVo);
    }

    // 格式化目录
    private List<FindWikiCatalogListRspVo> catalogCollation(List<FindWikiCatalogListRspVo> parentCatalogList, List<WikiCatalogDo> wikiCatalogDoList, Integer catalogLevel) {
        if (WikiCatalogLevelEnum.ONE.getValue().equals(catalogLevel)) {
            // 一级目录
            // 提取一级目录
            if (!CollectionUtils.isEmpty(wikiCatalogDoList)) {
                List<FindWikiCatalogListRspVo> vos = Lists.newArrayList();
                List<WikiCatalogDo> oneLevelCatalogDos = wikiCatalogDoList.stream()
                        .filter(wikiCatalogDo -> Objects.equals(wikiCatalogDo.getLevel(), catalogLevel))
                        .sorted(Comparator.comparing(WikiCatalogDo::getSort)) // 根据sort升序排列
                        .collect(Collectors.toList());

                // 将提取的一级目录do转换为vo
                for (WikiCatalogDo wikiCatalogDo : oneLevelCatalogDos) {
                    FindWikiCatalogListRspVo vo = FindWikiCatalogListRspVo.builder()
                            .id(wikiCatalogDo.getId())
                            .articleId(wikiCatalogDo.getArticleId())
                            .level(wikiCatalogDo.getLevel())
                            .sort(wikiCatalogDo.getSort())
                            .title(wikiCatalogDo.getTitle())
                            .build();
                    vos.add(vo);
                }
                // 为一级目录添加子节点
                vos = catalogCollation(vos, wikiCatalogDoList, catalogLevel + 1);
                return vos;
            }
            return null;
        } else {
            // 其他级别目录
            // 遍历父级目录
            if (!CollectionUtils.isEmpty(parentCatalogList)) {
                parentCatalogList.forEach(parentCatalog -> {
                    // 获取父级目录id
                    Long parentId = parentCatalog.getId();
                    // 提取子集目录do
                    List<WikiCatalogDo> childCatalogDos = wikiCatalogDoList.stream()
                            .filter(wikiCatalogDo -> Objects.equals(wikiCatalogDo.getParentId(), parentId) // 满足父目录为当前所遍历的父目录
                                    && Objects.equals(wikiCatalogDo.getLevel(), catalogLevel)) // 满足目标提取的目录等级
                            .sorted(Comparator.comparing(WikiCatalogDo::getSort))
                            .collect(Collectors.toList());
                    // 转换为vo
                    List<FindWikiCatalogListRspVo> childVos = null;
                    if (!CollectionUtils.isEmpty(childCatalogDos)) {
                        childVos = childCatalogDos.stream()
                                .map(wikiCatalogDo -> FindWikiCatalogListRspVo.builder()
                                        .id(wikiCatalogDo.getId())
                                        .level(wikiCatalogDo.getLevel())
                                        .sort(wikiCatalogDo.getSort())
                                        .title(wikiCatalogDo.getTitle())
                                        .articleId(wikiCatalogDo.getArticleId())
                                        .build())
                                .collect(Collectors.toList());
                        // 为子节点添加子节点
                        childVos = catalogCollation(childVos, wikiCatalogDoList, catalogLevel + 1);
                    }
                    // 设置父节点的child节点
                    parentCatalog.setChildren(childVos);
                });
            }
            return parentCatalogList;
        }
    }
}
